/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.icanci.operation.service.impl;

import cn.hutool.core.date.StopWatch;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.icanci.basic.commonutils.R;
import cn.icanci.basic.exception.ApplicationException;
import cn.icanci.operation.entity.Ticket;
import cn.icanci.operation.service.TicketService;
import cn.icanci.operation.service.UploadExcelService;
import cn.icanci.operation.utils.ExcelPaths;
import cn.icanci.operation.utils.TradeLogService;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;

/**
 * @author icanci
 * @date Created in 2021/04/29 17:48
 * @version 1.0
 */
@Service
@Slf4j
public class UploadExcelServiceImpl implements UploadExcelService {

    @Resource
    private TicketService   ticketService;
    @Resource
    private TradeLogService tradeLogService;

    /**
     * 上传的票
     * @param uploadFile 文件
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public R uploadTicket(MultipartFile uploadFile) throws ApplicationException {
        tradeLogService.setLogInfo("UPLOAD_EXCEL_SERVICE", "UPLOAD_TICKET", "");
        // 对文件进行解析
        if (null == uploadFile) {
            return R.error().message("解析失败，文件为空");
        }
        String uploadPath = ExcelPaths.EXCEL_PATH;
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }
        String fileName = uploadFile.getOriginalFilename();
        String originalFileName = fileName.substring(0, fileName.lastIndexOf("."));
        //获取文件名后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String newFileName = originalFileName + "_" + UUID.randomUUID().toString() + suffix;

        File file = new File(uploadPath, newFileName);
        try {
            uploadFile.transferTo(file);
        } catch (Exception e) {
            tradeLogService.error(log, "UploadExcelService 上传失败：{}", e.getMessage());
            return R.ok().message("上传失败");
        }
        // 开始解析
        tradeLogService.info(log, "UploadExcelService,newFileName,:{}", newFileName);
        try {
            StopWatch stopWatch = new StopWatch("UploadExcelService parser");
            stopWatch.start();

            ExcelReader reader = ExcelUtil.getReader(ExcelPaths.EXCEL_PATH + "/" + newFileName);
            List<List<Object>> read = reader.read();
            // 对读取的数据进行处理 包含横坐标，纵坐标，座位价格，是否可用，座位状态
            List<Ticket> ticketLists = Lists.newArrayList();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (int i = 1; i < read.size(); i++) {
                List<Object> temp = read.get(i);
                int index = 0;

                String startCity = String.valueOf(temp.get(index++).toString());
                String arriveCity = String.valueOf(temp.get(index++).toString());
                Date startDate = simpleDateFormat.parse(temp.get(index++).toString());
                Date arriveDate = simpleDateFormat.parse(temp.get(index++).toString());
                String startCityCode = String.valueOf(temp.get(index++).toString());
                String arriveCityCode = String.valueOf(temp.get(index++).toString());
                String gds = String.valueOf(temp.get(index++).toString());
                BigDecimal price = new BigDecimal(temp.get(index++).toString());
                Integer ticketLevel = Integer.valueOf(temp.get(index++).toString());
                Integer status = Integer.valueOf(temp.get(index++).toString());
                String flightNumber = String.valueOf(temp.get(index++).toString());
                String seatNumber = String.valueOf(temp.get(index++).toString());
                Integer aircraftNumber = Integer.valueOf(temp.get(index++).toString());
                // 查询一次数据
                int hasCount = ticketService.queryNumberByFlightNumber(flightNumber);
                if (hasCount > 0) {
                    tradeLogService.error(log, "此航班已经存在，加载失败,航班号：{}", flightNumber);
                    return R.error().message("此航班已经存在，加载失败");
                }
                // 保存座位的信息
                Ticket ticket = new Ticket();
                ticket.setStartCity(startCity);
                ticket.setArriveCity(arriveCity);
                ticket.setStartDate(startDate);
                ticket.setArriveDate(arriveDate);
                ticket.setStartCityCode(startCityCode);
                ticket.setArriveCityCode(arriveCityCode);
                ticket.setGds(gds);
                ticket.setPrice(price);
                ticket.setTicketLevel(ticketLevel);
                ticket.setStatus(status);
                ticket.setFlightNumber(flightNumber);
                ticket.setSeatNumber(seatNumber);
                ticket.setAircraftNumber(aircraftNumber);

                ticket.setCreateTime(new Date());
                ticket.setUpdateTime(new Date());
                tradeLogService.info(log, "机票信息为：{}", JSON.toJSONString(ticket));
                ticketLists.add(ticket);
            }
            ticketService.insertManyRow(ticketLists);
            stopWatch.stop();
            tradeLogService.info(log, "任务结束," + stopWatch.prettyPrint());
        } catch (Exception e) {
            tradeLogService.error(log, "解析失败，message:{}", e.getMessage());
            return R.error().message("解析失败，" + e.getMessage());
        } finally {
            tradeLogService.removeAll();
        }
        return R.ok().message("机票解析成功");
    }
}
